﻿using System;
using System.Runtime.Serialization;

namespace Infrastructure.Logging
{
    /// <summary>
    /// Hold operation response object.
    /// </summary>
    [DataContract(Namespace = "http://Schemas.com/Infrustructure/Contracts/V1")]
    public class BaseResponse
    {
        /// <summary>
        /// the error code of the response
        /// </summary>
        [DataMember(IsRequired = true)]
        public int ErrorCode { get; protected set; }

        /// <summary>
        /// the description of the error (empty string if there is no error)
        /// </summary>
        [DataMember(IsRequired = true)]
        public string ErrorDescription { get; protected set; }

        /// <summary>
        /// Init successful response object. 
        /// <div><see cref="ErrorCode"/> = 0</div>
        /// <div><see cref="ErrorDescription"/> = string.Empty.</div>
        /// </summary>
        public BaseResponse()
        {
            ErrorCode = 0;
            ErrorDescription = string.Empty;
        }

        /// <summary>
        /// Init response object with the given error code and description.
        /// </summary>
        /// <param name="errorCode">the error code of the response</param>
        /// <param name="errorDescription">the description of the error (not null)</param>
        /// <exception cref="ArgumentNullException"><paramref name="errorDescription"/> is null</exception>
        public BaseResponse( int errorCode, string errorDescription )
        {
            if (errorDescription == null)
                throw new ArgumentNullException( "errorDescription" );

            ErrorCode = errorCode;
            ErrorDescription = errorDescription;
        }

        /// <summary>
        /// Is the response represent successful response.
        /// <div>check that <see cref="ErrorCode"/> equals 0</div>
        /// </summary>
        public bool IsSuccessful
        {
            get { return ErrorCode == 0; }
        }

        /// <summary>
        /// Is the response represent failure response.
        /// <div>check that <see cref="ErrorCode"/> NOT equals 0</div>
        /// </summary>
        public bool IsFailure
        {
            get { return ErrorCode != 0; }
        }

        /// <summary>
        /// true - the error code set in the response object is in WCF error codes range.
        /// </summary>
        public bool IsWcfError
        {
            get { return (int)ErrorCodes.WcfGeneralError <= ErrorCode && ErrorCode < (int)ErrorCodes.WcfGeneralError + 100; }
        }

        /// <summary>
        /// Set the response object to error state with the given data.
        /// </summary>
        /// <param name="errorCode">the error code of the response</param>
        /// <param name="errorDescription">the description of the error (not null)</param>
        /// <exception cref="ArgumentNullException"><paramref name="errorDescription"/> is null</exception>
        public void SetError( int errorCode, string errorDescription )
        {
            ErrorCode = errorCode;
            ErrorDescription = errorDescription;
        }

        /// <summary>
        /// Set the response object to error state with the given data.
        /// </summary>
        /// <param name="errorCode">the error code of the response</param>
        /// <param name="errorDescriptionFormat">the description of the error (not null or empty)</param>
        /// <param name="args">the arguments for the error description format string (not null)</param>
        /// <exception cref="ArgumentException"><paramref name="errorDescriptionFormat"/> is null or empty</exception>
        /// <exception cref="ArgumentNullException"><paramref name="args"/> is null</exception>
        public void SetError(int errorCode, string errorDescriptionFormat, params object[] args )
        {
            if (string.IsNullOrEmpty(errorDescriptionFormat))
                throw new ArgumentException("errorDescriptionFormat");
            if (args == null)
                throw new ArgumentNullException("args");

            ErrorCode = errorCode;
            ErrorDescription = string.Format( errorDescriptionFormat, args );

        }

        /// <summary>
        /// Set the error in this response to the fields values in the given response.
        /// </summary>
        public void SetError(BaseResponse baseResponse)
        {
            ErrorCode = baseResponse.ErrorCode;
            ErrorDescription = baseResponse.ErrorDescription;
        }

        /// <summary>
        /// reset the error in the object to default (success with empty error description)
        /// </summary>
        public void ResetError()
        {
            SetError( 0, string.Empty );
        }

        public override string ToString()
        {
            return string.Format( "Code: {0}, Description: {1}", ErrorCode, ErrorDescription );
        }
    }
}
